package org.rc.web;

import com.google.appengine.api.memcache.stdimpl.GCacheFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheFactory;
import javax.cache.CacheManager;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.rc.dao.GenericDao;
import org.rc.dao.RaceDao;
import org.rc.model.Race;
import org.rc.model.SearchTerm;
import org.rc.model.Statistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Index servlet. Handle requests for /index.
 * Home page
 */
public class IndexServlet extends HttpServlet {

    private static final Logger LOGGER = LoggerFactory.getLogger(IndexServlet.class);
    private GenericDao<Statistics> statisticsDao = new GenericDao<Statistics>(Statistics.class);
    private GenericDao<SearchTerm> searchTermDao = new GenericDao<SearchTerm>(SearchTerm.class);
    private RaceDao raceDao = new RaceDao();
    protected Cache cache;

    public IndexServlet() {
        Map props = new HashMap();
        props.put(GCacheFactory.EXPIRATION_DELTA, 14400);//4hrs cache expiry
        try {
            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
            cache = cacheFactory.createCache(props);
        } catch (CacheException e) {
            LOGGER.error("error setting up cache", e);
        }
    }

    /**
     * Process GET. 
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException 
     */
    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        Long totalRaces = (Long) cache.get("totalRacesStats");
        Long totalResults = (Long) cache.get("totalResultsStats");
        Long totalAthletes = (Long) cache.get("totalAthletesStats");

        if (totalRaces == null) {
            totalResults = new Long(0);
            totalAthletes = new Long(0);
            totalRaces = new Long(0);
            for (Statistics rf : statisticsDao.getAll()) {
                totalRaces += rf.getNumberOfRaces();
                totalResults += rf.getNumberOfResults();
            }
            cache.put("totalRacesStats", totalRaces);
            cache.put("totalResultsStats", totalResults);
            cache.put("totalAthletesStats", totalAthletes);
        }
        request.setAttribute("totalRaces", totalRaces);
        request.setAttribute("totalResults", totalResults);
        request.setAttribute("totalAthletes", totalAthletes);
        request.setAttribute("latestRace", getLatestRace());
        request.setAttribute("latestSearches", searchTermDao.getTop(15,"-date"));

        forward(request, response, "index.jsp");
    }

    /**
     * Forwards request and response to given path. Handles any exceptions
     * caused by forward target by printing them to logger.
     * 
     * @param request 
     * @param response
     * @param path 
     */
    protected void forward(HttpServletRequest request,
            HttpServletResponse response, String path) {
        try {
            RequestDispatcher rd = request.getRequestDispatcher(path);
            rd.forward(request, response);
        } catch (Throwable tr) {
            if (LOGGER.isErrorEnabled()) {
                LOGGER.error("Cought Exception: " + tr.getMessage());
                LOGGER.debug("StackTrace:", tr);
            }
        }
    }

    /**
     * Get the latest race from datastore/cache
     * @return
     */
    private Race getLatestRace() {
        Race result = (Race) cache.get("latestRaceStat");
        if(result==null) {
            List<Race> results = raceDao.getTop(1,"-date");
            if(!results.isEmpty()) {
                result=results.get(0);
                cache.put("latestRaceStat", result);
            }
        }
        return result;
    }

    /**
     * Determine if the request is an ajax cal from datatables
     * @param request
     * @return
     */
    protected boolean isDataTablesRequest(HttpServletRequest request) {
        return request.getParameter("sEcho")!=null;
    }

}
